package cn.com.surker.lab.service.impl;

import cn.com.surker.base.system.dao.SysStorageDao;
import cn.com.surker.base.system.dao.SysStorageMatchDao;
import cn.com.surker.base.system.vo.SysStorageVo;
import cn.com.surker.common.MessageCenterException;
import cn.com.surker.enums.StateEnum;
import cn.com.surker.enums.material.MaterialBreedTypeEnum;
import cn.com.surker.enums.production.invoice.InvoiceCreateTypeEnum;
import cn.com.surker.lab.dao.LabExpendDao;
import cn.com.surker.lab.dao.LabLevelOptimizeDao;
import cn.com.surker.lab.dao.LabLevelOptimizeMaterialDao;
import cn.com.surker.external.entity.LabExpendB;
import cn.com.surker.external.dao.LabExpendBDao;
import cn.com.surker.lab.entity.LabLevelOptimizeMaterial;
import cn.com.surker.lab.service.LabExpendBService;
import cn.com.surker.lab.vo.LabExpendVo;
import cn.com.surker.lab.vo.LabExpendVoB;
import cn.com.surker.lab.vo.OptimizeMaterialVo;
import cn.com.surker.oa.dao.OaMaterialDao;
import cn.com.surker.oa.entity.OaMaterial;
import cn.com.surker.production.entity.vo.ProductionInvoiceVo;
import cn.com.surker.util.DateUtil;
import cn.com.surker.util.StringUtils;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.com.surker.spring.RestResultDto;

import javax.annotation.Resource;
import java.util.*;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

/**
 * <p>
 * 工控机B库消耗表 服务实现类
 * </p>
 *
 * @author admin
 * @since 2025-03-03
 */
public abstract class LabExpendBBaseImpl extends ServiceImpl<LabExpendBDao, LabExpendB> implements LabExpendBService {

	@Resource
	protected LabExpendBDao expendBDao;
	@Resource
	protected LabExpendDao expendDao;
	@Resource
	protected LabLevelOptimizeDao optimizeDao;
	@Resource
	protected LabLevelOptimizeMaterialDao optimizeMaterialDao;
	@Resource
	protected SysStorageDao storageDao;
	@Resource
	protected SysStorageMatchDao storageMatchDao;
	@Resource
	private OaMaterialDao materialDao;

	private static Map<Long, List<OptimizeMaterialVo>> strengthMaterial = new HashMap<>();
	private static Map<Integer, String> breedTypeMap = new HashMap<>();

	/**
	 * 计算b库消耗
	 * @return
	 */
	public RestResultDto calcBExpend(String dbCode, String startTime, String endTime) {
		if (StringUtils.isNull(dbCode))
			throw new MessageCenterException("dbCode为空");
		if (StringUtils.isNull(startTime))
			startTime = null;
		if (StringUtils.isNull(endTime))
			endTime = null;
		List<ProductionInvoiceVo> invoiceList = expendBDao.findNoInvoice(startTime, endTime);
		if (invoiceList == null || invoiceList.size() == 0)
			throw new MessageCenterException("没有需要执行的发货单数据");
		strengthMaterial = new HashMap<>();
		breedTypeMap = new HashMap<>();
		for (int i = 0; i < MaterialBreedTypeEnum.values().length; i++) {
			breedTypeMap.put(MaterialBreedTypeEnum.values()[i].getCode(), MaterialBreedTypeEnum.values()[i].getDescription());
		}
		for (ProductionInvoiceVo invoice : invoiceList) {
//			Long invoiceId = invoice.getId();
//			Double sendStere = StringUtils.convertDouble(invoice.getSendStere());
			calcStrengthExpend(dbCode, invoice);
		}

		return RestResultDto.success("计算完成");
	}

	/**
	 * 计算发货单消耗
	 * @param dbCode
	 * @param startTime
	 * @param endTime
	 * @return
	 */
	public RestResultDto calcDeliveryBExpend(String dbCode, Integer type, String startTime, String endTime) {
		if (StringUtils.isNull(type))
			type = InvoiceCreateTypeEnum.EMPTY_TICKET.getCode();
		Date nowDate = new Date();
		if (StringUtils.isNull(startTime))
			startTime = DateUtil.convertString(DateUtil.convertBeforeDayDate(nowDate, 30));
		if (StringUtils.isNull(endTime))
			endTime = DateUtil.convertString(nowDate);
		List<ProductionInvoiceVo> invoiceList = expendBDao.findNoInvoice(startTime, endTime);
		if (invoiceList == null || invoiceList.size() == 0)
			throw new MessageCenterException("没有需要执行的发货单数据");
		for (ProductionInvoiceVo invoice : invoiceList) {
//			Long invoiceId = invoice.getId();
//			Double sendStere = StringUtils.convertDouble(invoice.getSendStere());
			if (StringUtils.isNull(invoice.getId()))
				continue;
			calcStrengthExpend(dbCode, invoice);
		}

		return RestResultDto.success("计算完成");
	}

	@Override
	public List<LabExpendVoB> findNotWrite() {
		List<LabExpendVoB> labExpendBS = expendBDao.findNotWrite();
		return labExpendBS;
	}

	@Override
	public int setUpWrite(List<Long> ids) {
		if (ids == null || ids.isEmpty()) {
			log.error("B库数据置为回写无数据");
			return -1;
		}
		UpdateWrapper<LabExpendB> uw = new UpdateWrapper<>();
		uw.in("id", ids);
		uw.set("is_write", StateEnum.DISABLED.getCode());
		int update = expendBDao.update(new LabExpendB(), uw);
		return update;
	}
	public static void main(String[] args){
		System.out.println(21.0 / 4);
		System.out.println(21.0 % 4);
	}
	/**
	 * 计算发货单标号B库消耗
	 * @param dbCode
	 * @param invoice
	 */
	private void calcStrengthExpend(String dbCode,ProductionInvoiceVo invoice) {
		Long invoiceId = invoice.getId();
		Double sendStere = StringUtils.convertDouble(invoice.getSumSendStere());//发货方量合计
		Double sumBatchStere = StringUtils.convertDouble(invoice.getBatchStere());//盘方量合计
		Integer sumBatchNum = StringUtils.convertInteger(invoice.getBatchNum());//累计盘号
		Double stereRatio = 1.0;
		if (sendStere.doubleValue() < sumBatchStere.doubleValue())
			sendStere = sumBatchStere;
		if (sumBatchStere > 0 && sendStere > sumBatchStere)//计算累计发货与盘方量的差量系数
			stereRatio = StringUtils.divideDouble(sendStere * 100,sumBatchStere * 100, 4);
//		Integer calcBatchNum = StringUtils.convertInteger(sendStere / 4);
//		if (sendStere % 4 > 0)//按4方量计算盘数
//			calcBatchNum++;

		Long strengthId = null;
		if (!StringUtils.isNull(invoice.getStrengthId()))
			strengthId = invoice.getStrengthId();
		List<OptimizeMaterialVo> optimizeMaterialList = null;

		if (strengthId == null) {
			QueryWrapper<LabLevelOptimizeMaterial> optimizeQuery = new QueryWrapper<>();
			optimizeQuery.eq("a.status", 0);
			optimizeQuery.inSql("a.level_optimize_id", "select id from lab_level_optimize where status = 0 " +
					"and strength_id in (select strength_id from production_indent \n" +
					"where status = 0 and id in (select indent_id from production_invoice " +
					"where status = 0 and id = " + invoice.getId() + "))  and id in (select max(id) id from lab_level_optimize group by strength_id )");//按任务单强度等级获取标准材料
			optimizeMaterialList = optimizeMaterialDao.findByOptimizeStrength(optimizeQuery);
			if (optimizeMaterialList == null || optimizeMaterialList.size() == 0) {
				optimizeQuery = new QueryWrapper<>();
				optimizeQuery.eq("a.status", 0);
				optimizeQuery.inSql("a.level_optimize_id", "select id from lab_level_optimize where status = 0 \n" +
						"and id in (select optimize_material_id from lab_level_construct where status = 0 and strength_id in (\n" +
						"select strength_id from production_indent \n" +
						"where status = 0 and id in (select indent_id from production_invoice where status = 0 and id = " +invoiceId + "))\n" +
						" and id in (select max(id) id from lab_level_optimize group by strength_id ))");
				optimizeMaterialList = optimizeMaterialDao.findByOptimizeStrength(optimizeQuery);
				if (optimizeMaterialList == null || optimizeMaterialList.size() == 0)
					return;
			}
		} else {
			if (strengthMaterial.containsKey(strengthId)) {
				optimizeMaterialList = strengthMaterial.get(strengthId);
			} else {
				QueryWrapper<LabLevelOptimizeMaterial> optimizeQuery = new QueryWrapper<>();
				optimizeQuery.eq("a.status", 0);
				optimizeQuery.inSql("a.level_optimize_id", "select id from lab_level_optimize where status = 0 " +
						"and strength_id in (select strength_id from production_indent \n" +
						"where status = 0 and id in (select indent_id from production_invoice " +
						"where status = 0 and id = " + invoice.getId() + "))  and id in (select max(id) id from lab_level_optimize group by strength_id )");//按任务单强度等级获取标准材料
				optimizeMaterialList = optimizeMaterialDao.findByOptimizeStrength(optimizeQuery);
				if (optimizeMaterialList == null || optimizeMaterialList.size() == 0) {
					optimizeQuery = new QueryWrapper<>();
					optimizeQuery.eq("a.status", 0);
					optimizeQuery.inSql("a.level_optimize_id", "select id from lab_level_optimize where status = 0 \n" +
							"and id in (select optimize_material_id from lab_level_construct where status = 0 and strength_id in (\n" +
							"select strength_id from production_indent \n" +
							"where status = 0 and id in (select indent_id from production_invoice where status = 0 and id = " +invoiceId + "))\n" +
							" and id in (select max(id) id from lab_level_optimize group by strength_id ))");
					optimizeMaterialList = optimizeMaterialDao.findByOptimizeStrength(optimizeQuery);
					if (optimizeMaterialList == null || optimizeMaterialList.size() == 0)
						return;
				}
				strengthMaterial.put(strengthId, optimizeMaterialList);
			}
		}

		List<LabExpendVo> expendVoList = expendDao.findByInvoiceV1(dbCode, invoiceId);
		if (expendVoList == null || expendVoList.size() == 0)
			return;

		Long lineId = null;
//		List<String> keyList = new ArrayList<>();
		Map<Integer, Map<Integer, LabExpendVo>> expendVoMap = new HashMap<>();//盘号,材料类型,消耗
		Map<Integer, Double> batchStereMap = new HashMap<>();//盘方量数据
		Map<Integer, Long> batchIdMap = new HashMap<>();//盘ID数据
		Map<Integer, Date> useTimeMap = new HashMap<>();//下料时间
		for (LabExpendVo expendVo : expendVoList) {
			if (StringUtils.isNull(expendVo.getBatchId()) || StringUtils.isNull(expendVo.getBatchNum())
					|| StringUtils.isNull(expendVo.getMaterialBreedType()))
				continue;
			Integer batchNum = expendVo.getBatchNum();
			Integer breedType = expendVo.getMaterialBreedType();

			if (!StringUtils.isNull(expendVo.getBatchStere())) {
				if (!batchStereMap.containsKey(batchNum))
					batchStereMap.put(batchNum, expendVo.getBatchStere());
			}
			if (!StringUtils.isNull(expendVo.getBatchId())) {
				if (!batchIdMap.containsKey(batchNum))
					batchIdMap.put(batchNum, expendVo.getBatchId());
			}
			if (!StringUtils.isNull(expendVo.getUseTime())) {
				if (!useTimeMap.containsKey(batchNum))
					useTimeMap.put(batchNum, expendVo.getUseTime());
			} else {
				if (!useTimeMap.containsKey(batchNum))
					useTimeMap.put(batchNum, expendVo.getBatchTime());
			}
			if (expendVoMap.containsKey(batchNum)) {
				Map<Integer, LabExpendVo> breedMap = expendVoMap.get(batchNum);
				breedMap.put(breedType, expendVo);
				expendVoMap.put(batchNum, breedMap);
			} else {
				Map<Integer, LabExpendVo> breedMap = new HashMap<>();
				breedMap.put(breedType, expendVo);
				expendVoMap.put(batchNum, breedMap);
			}
			if (lineId == null)//生产线
				if (!StringUtils.isNull(expendVo.getLineId()))
					lineId = expendVo.getLineId();
		}
		if (expendVoMap == null || expendVoMap.keySet().size() == 0)
			return;
		Date nowDate = new Date();
		List<LabExpendB> expendBList = new ArrayList<>();
		for (Integer batchNum : expendVoMap.keySet()) {
			Map<Integer, LabExpendVo> breedMap = expendVoMap.get(batchNum);
			for (OptimizeMaterialVo materialVo : optimizeMaterialList) {
				if (StringUtils.isNull(materialVo.getMaterialBreedType()))
					continue;
				Integer breedType = materialVo.getMaterialBreedType();//材料品类
				LabExpendVo expendVo = breedMap.get(breedType);
				Double batchStere = StringUtils.formatDouble(batchStereMap.get(batchNum) * stereRatio, 2);//盘方量
				Date useTime = useTimeMap.get(batchNum);
				Long batchId = StringUtils.convertLong(batchIdMap.get(batchNum));//盘ID
				Double rate = materialRate(breedType);//浮动率
				Double setDosage = materialVo.getUsed();
				Double controlSetQuantity = StringUtils.formatDouble(batchStere * materialRate(breedType) * setDosage, 2);
				Double optimizeQuantity = StringUtils.formatDouble(setDosage, 2);
				Double dosage = StringUtils.formatDouble(batchStere * rate * setDosage, 2);
//				if (expendVo != null && !StringUtils.isNull(expendVo.getSetDosage()))
//					controlSetQuantity = StringUtils.convertDouble(expendVo.getSetDosage());
//				if (expendVo != null && !StringUtils.isNull(expendVo.getLabDosage()))
//					optimizeQuantity = StringUtils.convertDouble(expendVo.getLabDosage());
				Integer total = expendBDao.findInvoiceBatch(invoiceId, breedType, batchNum);//查询是否存在已增加数据
				if (total > 0)
					continue;
				if (breedMap.containsKey(breedType)) {
					LabExpendB expendB = null;
					if (expendVo == null) {//如果工控下料数据的材料未匹配标准库
						expendB = new LabExpendB(invoiceId, lineId, materialVo.getMaterialId(), null,
								"", batchId, 0, 0, materialVo.getLevelOptimizeId(), optimizeQuantity,
								0.0, controlSetQuantity, dosage, 0.0, useTime, null);
					} else {
						expendB = BeanUtil.copyProperties(expendVo, LabExpendB.class);
					}
					expendB.setMaterialId(materialVo.getMaterialId());
					expendB.setUseTime(useTime);
					expendB.setProStere(batchStere);
					expendB.setId(null);
					expendB.setIsStorage(0);
					expendB.setOptimizeQuantity(optimizeQuantity);
					expendB.setControlRealQuantity(dosage);
					expendB.setControlSetQuantity(controlSetQuantity);
					expendB.setUpdateTime(useTime);
					expendB.setBatchTime(useTime);
					expendB.setProStere(batchStere);
					expendBList.add(expendB);
				} else {
					LabExpendB expendB = new LabExpendB(invoiceId, lineId, materialVo.getMaterialId(), null,
							"", batchId, 0, 0, materialVo.getLevelOptimizeId(), optimizeQuantity,
							0.0, controlSetQuantity, dosage, 0.0, useTime, null);
					expendB.setUseTime(useTime);
					expendB.setMaterialId(materialVo.getMaterialId());
					expendB.setStatus(0);
					expendB.setIsStorage(0);
					expendB.setOptimizeQuantity(optimizeQuantity);
					expendB.setControlRealQuantity(dosage);
					expendB.setControlSetQuantity(controlSetQuantity);
					expendB.setCreateTime(nowDate);
					expendB.setUpdateTime(useTime);
					expendB.setBatchTime(useTime);
					expendB.setProStere(batchStere);
					List<SysStorageVo> storageList = storageDao.findByMaterialV1(lineId, breedType);
					if (storageList != null && storageList.size() > 0) {
						Random rand = new Random();
						int randomNum = 0;
						if (storageList.size() > 1)
							randomNum = rand.nextInt(storageList.size() - 1);
						if (randomNum < storageList.size()) {
							SysStorageVo storageVo = storageList.get(randomNum);
							expendB.setControlStorage(storageVo.getControlStorage());
							expendB.setControlMaterial(storageVo.getNameNorms());
							expendB.setStorageId(storageVo.getStorageId());
						} else {
							String breedTypeName = StringUtils.convertString(breedTypeMap.get(breedType));
							if (!StringUtils.isNull(breedTypeName) && breedType != null && breedType != 0) {
								expendB.setControlMaterial(breedTypeName);
								expendB.setControlStorage(breedTypeName + rand.nextInt(1) + 1);
							} else {
								expendB.setControlStorage("工控仓位" + rand.nextInt(1) + 1);
							}
						}
					} else {
						Random rand = new Random();
						String breedTypeName = StringUtils.convertString(breedTypeMap.get(breedType));
						if (!StringUtils.isNull(breedTypeName) && breedType != null && breedType != 0) {
							expendB.setControlMaterial(breedTypeName);
							expendB.setControlStorage(breedTypeName + rand.nextInt(1) + 1);
						} else {
							expendB.setControlStorage("工控仓位" + rand.nextInt(1) + 1);
						}
					}
					expendBList.add(expendB);
				}
			}
		}
		if (expendBList == null || expendBList.size() == 0)
			return;
		expendBDao.saveBatch(expendBList);
	}

	private Double materialRate(Integer breedType) {//获取配比浮动比例
		if (breedType == MaterialBreedTypeEnum.GF.getCode()) {
			Random rand = new Random();
			int randomNum = 1000 + rand.nextInt(10) + 1;
			return StringUtils.formatDouble(randomNum / 1000.0, 3);
		} else {
			Random rand = new Random();
			int randomNum = 1000 + rand.nextInt(20) + 1;
			return StringUtils.formatDouble(randomNum / 1000.0, 3);
		}
	}

}